<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */

namespace Common\Kernel\Model;

use Hyperf\Collection\Arr;
use Hyperf\Database\Model\SoftDeletes;
use Hyperf\Database\Query\Expression;
use Hyperf\DbConnection\Model\Model as BaseModel;
use Hyperf\Di\Annotation\Inject;

/**
 * 基础模型类
 */
abstract class Model extends BaseModel
{
    const CREATED_AT = 'created_at';

    const UPDATED_AT = 'updated_at';

    #[Inject]
    protected Grammar $grammar;

    /**
     * 批量修改
     *
     * @param array $multipleData
     * @param string $key
     * @return int
     * @throws \Exception
     */
    public function updateBatch(array $multipleData = [], string $key = 'id'): int
    {
        if (empty($multipleData)) {
            return 0;
        }

        $builder = $this->getQuery();

        return $builder->connection->update($this->grammar->compileBatchUpdate($builder, $multipleData, $key), $this->_cleanBindings(Arr::flatten($multipleData, 1)));
    }

    /**
     * 批量插入，如果不存在则更新.
     *
     * @param array $values
     * @return bool
     */
    public function insertOrUpdate(array $values): bool
    {
        if (empty($values)) {
            return false;
        }

        if (! is_array(reset($values))) {
            $values = [$values];
        } else {
            foreach ($values as $key => $value) {
                ksort($value);
                $values[$key] = $value;
            }
        }

        $builder = $this->getQuery();

        $this->grammar->setTablePrefix($builder->connection->getTablePrefix());

        return $builder->connection->insert($this->grammar->compileInsertOrUpdate($builder, $values), $this->_cleanBindings(Arr::flatten($values, 1)));
    }

    /**
     * Remove all the expressions from a list of bindings.
     */
    protected function _cleanBindings(array $bindings): array
    {
        return array_values(array_filter($bindings, function ($binding) {
            return ! $binding instanceof Expression;
        }));
    }
}
